//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-26
// @Time:下午3:05
//

#ifndef GEEJOAN_GEEJOANMD5_H
#define GEEJOAN_GEEJOANMD5_H


#include <string>
#include <fstream>

/* Type define */
typedef unsigned char byte;
typedef unsigned long ulong;

using std::string;
using std::ifstream;

/**
 * @brief 该 MD5 算法的仅用于 独立编译的版本.不依赖openssl 的实现
 * 完整加密工具包 到 SecurityCommon 模块实现
 */
class GeeJoanMD5
{
public:
    GeeJoanMD5();

    GeeJoanMD5(const void *input, size_t length);

    GeeJoanMD5(const string &str);

    GeeJoanMD5(ifstream &in);

    void update(const void *input, size_t length);

    void update(const string &str);

    void update(ifstream &in);

    const byte *digest();

    string toString();

    void reset();

private:
    void update(const byte *input, size_t length);

    void final();

    void transform(const byte block[64]);

    void encode(const ulong *input, byte *output, size_t length);

    void decode(const byte *input, ulong *output, size_t length);

    string bytesToHexString(const byte *input, size_t length);

    /* class uncopyable */
    GeeJoanMD5(const GeeJoanMD5 &);

    GeeJoanMD5 &operator=(const GeeJoanMD5 &);

private:
    ulong _state[4];    /* state (ABCD) */
    ulong _count[2];    /* number of bits, modulo 2^64 (low-order word first) */
    byte _buffer[64];    /* input buffer */
    byte _digest[16];    /* message digest */
    bool _finished;        /* calculate finished ? */

    static const byte PADDING[64];    /* padding for calculate */
    static const char HEX[16];
    static const size_t BUFFER_SIZE = 1024;
};


#endif //GEEJOAN_GEEJOANMD5_H
